package org.example.lease.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.example.lease.mapper.ApartmentInfoMapper;
import org.example.lease.model.entities.*;
import org.example.lease.model.enums.ItemType;
import org.example.lease.service.*;
import org.example.lease.vo.apartment.ApartmentDetailVo;
import org.example.lease.vo.apartment.ApartmentItemVo;
import org.example.lease.vo.apartment.ApartmentQueryVo;
import org.example.lease.vo.apartment.ApartmentSubmitVo;
import org.example.lease.vo.fee.FeeValueVo;
import org.example.lease.vo.graph.GraphVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 宋孟林
 * @description 本类处理公寓信息涉及的业务逻辑有
 * 公寓-图片信息 2
 * 公寓-配套关系-配套 3
 * 公寓-标签关系-标签 3
 * 公寓-杂费值关系-杂费值-杂费名称 4
 * 公寓-区县信息-城市信息-省份信息-4
 * @date: 2025/5/12 16:52
 */
@Service
@Slf4j
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
        implements ApartmentInfoService {
    @Resource
    private ApartmentInfoMapper apartmentInfoMapper;
    @Resource
    private ApartmentFacilityService apartmentFacilityService;
    @Resource
    private ApartmentLabelService apartmentLabelService;
    @Resource
    private ApartmentFeeValueService apartmentFeeValueService;
    @Resource
    private GraphInfoService graphInfoService;

    @Transactional
    @Override
    public void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {
        //因为涉及到更新逻辑，所以判断这个实体是否是已经存在的id，如果是已经存在的id那么说明是更新逻辑
        //更新逻辑的话先删除之前的图片，配套，标签，杂费等信息，然后再删除，如果不是更新逻辑，就直接执行插入逻辑
        boolean isUpdate = apartmentSubmitVo.getId() != null;
        //更新或插入基本的配套 信息内容
        this.saveOrUpdate(apartmentSubmitVo);
        Long apartmentId = apartmentSubmitVo.getId(); //取出公寓id
        if (isUpdate) {
            //如果是删除逻辑，先删除已经存在的图片信息
            graphInfoService.remove(Wrappers.lambdaQuery(GraphInfo.class)
                    .eq(GraphInfo::getItemId, apartmentId)
                    .eq(GraphInfo::getItemType, ItemType.APARTMENT));
            //删除公寓和配套之间的信息
            apartmentFacilityService.remove(Wrappers.lambdaQuery(ApartmentFacility.class)
                    .eq(ApartmentFacility::getApartmentId, apartmentId));
            //删除公寓和标签之间的信息
            apartmentLabelService.remove(Wrappers.lambdaQuery(ApartmentLabel.class)
                    .eq(ApartmentLabel::getApartmentId, apartmentId));
            //删除公寓和杂费值之间的信息
            apartmentFeeValueService.remove(Wrappers.lambdaQuery(ApartmentFeeValue.class)
                    .eq(ApartmentFeeValue::getApartmentId, apartmentId));
            log.info("公寓-配套-标签-图片-杂费值之间的关系表数据已经删除");
        }
        //插入图片逻辑,图片非空才插入
        List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
        if (!CollectionUtils.isEmpty(graphVoList)){
            //将VO中的图片URL和name都存入GraphInfo中
            ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
            for (GraphVo graphVo : graphVoList) {
                //保存图像的时候观察图像的实体类，不仅要保存图片的名字URL还要保存所属的对象类型和id
                //所以新创建一个graphInfo对象
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setName(graphVo.getName());
                graphInfo.setUrl(graphInfo.getUrl());
                graphInfo.setItemType(ItemType.APARTMENT);
                graphInfo.setItemId(apartmentId);
                //添加到图片集合中
                graphInfoList.add(graphInfo);
            }
            graphInfoService.saveBatch(graphInfoList);
        }
        //插入公寓-配套相关信息
        List<Long> facilityInfoIds = apartmentSubmitVo.getFacilityInfoIds();
        if (!CollectionUtils.isEmpty(facilityInfoIds)){
            ArrayList<ApartmentFacility> apartmentFacilityList = new ArrayList<>();
            for (Long facilityInfoId : facilityInfoIds) {
                ApartmentFacility apartmentFacility = ApartmentFacility.builder().facilityId(facilityInfoId).apartmentId(apartmentId).build();
                apartmentFacilityList.add(apartmentFacility);
            }
            apartmentFacilityService.saveBatch(apartmentFacilityList);
        }
        //插入公寓和标签关联的信息
        List<Long> labelIds = apartmentSubmitVo.getLabelIds();
        if (!CollectionUtils.isEmpty(labelIds)){
            ArrayList<ApartmentLabel> apartmentLabelList = new ArrayList<>();
            for (Long labelId : labelIds) {
                ApartmentLabel apartmentLabel = ApartmentLabel.builder().labelId(labelId).apartmentId(apartmentId).build();
                apartmentLabelList.add(apartmentLabel);
            }
            apartmentLabelService.saveBatch(apartmentLabelList);
        }
        //插入杂费列表相关信息
        List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
        if (!CollectionUtils.isEmpty(feeValueIds)){
            ArrayList<ApartmentFeeValue> apartmentFeeValues = new ArrayList<>();
            for (Long feeValueId : feeValueIds) {
                ApartmentFeeValue apartmentFeeValue = ApartmentFeeValue.builder().feeValueId(feeValueId).apartmentId(apartmentId).build();
                apartmentFeeValues.add(apartmentFeeValue);
            }
            apartmentFeeValueService.saveBatch(apartmentFeeValues);
        }
    }

    @Override
    public IPage<ApartmentItemVo> pageApartmentItemByQuery(IPage<ApartmentItemVo> page, ApartmentQueryVo apartmentQueryVo) {
        return apartmentInfoMapper.pageApartmentItemByQuery(page, apartmentQueryVo);
    }

    /**
     * 根据id查询公寓详细信息
     * 公寓-公寓配套信息
     * 公寓-公寓标签
     * 公寓-杂费值信息
     * 公寓-图片列表
     * 将以上四部分内容封装到ApartmentDetailVo中
     * @param id id
     * @return apartmentDetailVo
     */
    @Override
    public ApartmentDetailVo getDetailById(Long id) {
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        ApartmentInfo apartmentInfo = apartmentInfoMapper.selectById(id);
        if (apartmentInfo == null){
            return null;
        }
        log.info("公寓基本信息查询完毕:{}", apartmentInfo);
        //使用spring的工具包，将apartmentInfo对象中的属性值复制到apartmentDetailVo
        BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);
        //查询图片列表
        List<GraphVo> graphVoList = apartmentInfoMapper.selectGraphVoList(ItemType.APARTMENT, id);
        log.info("与公寓关联的图片集合查询完毕:{}", graphVoList);
        apartmentDetailVo.setGraphVoList(graphVoList);
        //查询配套列表
        List<FacilityInfo> facilityInfoList = apartmentInfoMapper.selectFacilityInfoList(id);
        log.info("与公寓关联的配套集合查询完毕:{}", facilityInfoList);
        apartmentDetailVo.setFacilityInfoList(facilityInfoList);
        //查询标签列表
        List<LabelInfo> labelInfoList = apartmentInfoMapper.selectLabelInfoList(ItemType.APARTMENT, id);
        log.info("与公寓关联的标签集合查询完毕:{}", labelInfoList);
        apartmentDetailVo.setLabelInfoList(labelInfoList);
        //查询杂费之列表
        List<FeeValueVo> feeValueVoList = apartmentInfoMapper.selectFeeValueVoList(id);
        log.info("与公寓关联的杂费值集合查询完毕:{}", feeValueVoList);
        apartmentDetailVo.setFeeValueVoList(feeValueVoList);
        return apartmentDetailVo;
    }

    /**
     * 根据id删除公寓信息，以及关联的表信息
     * 1.删除公寓基本表信息
     * 2.删除关联表中和此公寓相关的数据
     * @param id 公寓id
     */
    @Transactional
    @Override
    public void removeApartmentInfoById(Long id) {
        int i = apartmentInfoMapper.deleteById(id);
        if (i > 0){
            //删除和此公寓相关的图片
            graphInfoService.remove(Wrappers.lambdaQuery(GraphInfo.class)
                    .eq(GraphInfo::getItemType, ItemType.APARTMENT).eq(GraphInfo::getItemId, id));
            //删除和此公寓相关的配套
            apartmentFacilityService.remove(Wrappers.lambdaQuery(ApartmentFacility.class)
                    .eq(ApartmentFacility::getApartmentId, id));
            //删除和此公寓相关的标签
            apartmentLabelService.remove(Wrappers.lambdaQuery(ApartmentLabel.class)
                    .eq(ApartmentLabel::getApartmentId, id));
            //删除和此公寓相关的杂费值
            apartmentFeeValueService.remove(Wrappers.lambdaQuery(ApartmentFeeValue.class)
                    .eq(ApartmentFeeValue::getApartmentId, id));
        }
    }
}




